/*
 * @Author: Wangjun
 * @Date: 2023-02-27 14:48:23
 * @LastEditTime: 2025-06-13 17:40:13
 * @LastEditors: wangjun haodreams@163.com
 * @Description:
 * @FilePath: \xrop2opd:\go\src\gitee.com\haodreams\libs\fixedqueue\queue.go
 * hnxr
 */
package fixedlist

import (
	"io"
	"math"
)

// 固定大小的队列
type NumQueue struct {
	array   []float64
	reserve int
	head    uint32 // 队首位置
	tail    uint32 // 队尾的下一个位置
	cap     uint32 // 最大容量
	size    uint32 // 当前数据个数
}

// 创建新的固定大小队列
func NewNumQueue(size int) *NumQueue {
	m := new(NumQueue)
	m.SetSize(size)
	return m
}

// 创建新的固定大小队列
func NewFixReserveQueue(size, reserve int) *NumQueue {
	m := new(NumQueue)
	m.SetSize(size)
	m.reserve = reserve
	return m
}

// 重置队列
func (m *NumQueue) Reset() {
	m.head = 0
	m.tail = 0
	m.size = 0
	// // 帮助GC回收内存
	// for i := range m.array {
	// 	m.array[i] = nil
	// }
}

// 设置队列大小
func (m *NumQueue) SetSize(maxLines int) {
	if maxLines < 2 {
		maxLines = 2
	}
	if maxLines > 1000000 {
		maxLines = 1000000
	}
	if maxLines == int(m.cap) {
		return
	}
	m.array = make([]float64, maxLines)
	m.cap = uint32(maxLines)
	m.Reset()
}

// 获取队列大小
func (m *NumQueue) Len() int {
	return int(m.size)
}

// 检查队列是否为空
func (m *NumQueue) IsEmpty() bool {
	return m.size == 0
}

// 检查队列是否已满
func (m *NumQueue) IsFull() bool {
	return m.size == m.cap
}

// 入队操作
func (m *NumQueue) Push(e float64) {
	if m.IsFull() {
		// 队列已满，覆盖队首元素
		m.array[m.head] = e
		m.head = (m.head + 1) % m.cap
		m.tail = m.head
	} else {
		m.array[m.tail] = e
		m.tail = (m.tail + 1) % m.cap
		m.size++
	}
}

// 获取指定位置的元素
func (m *NumQueue) Get(index int) float64 {
	if index < 0 || index >= int(m.size) {
		return -1
	}
	pos := (m.head + uint32(index)) % m.cap
	return m.array[pos]
}

// 倒序获取指定位置的元素
func (m *NumQueue) GetDesc(index int) float64 {
	if index < 0 || index >= int(m.size) {
		return -1
	}
	pos := (m.tail - uint32(index) - 1 + m.cap) % m.cap
	return m.array[pos]
}

// 出队操作
func (m *NumQueue) Pop() (e float64, err error) {
	if m.IsEmpty() {
		return -1, io.EOF
	}
	e = m.array[m.head]
	m.head = (m.head + 1) % m.cap
	m.size--
	return
}

// 辅助函数：返回两数中的较小值
func (m *NumQueue) min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// 辅助函数：生成索引序列
func (m *NumQueue) generateIndices(start, end int, asc bool) []int {
	if asc {
		indices := make([]int, end-start)
		for i := range indices {
			indices[i] = start + i
		}
		return indices
	} else {
		indices := make([]int, end-start)
		for i := range indices {
			indices[i] = end - 1 - i
		}
		return indices
	}
}

// 按队列顺序获取元素（先进先出）
func (m *NumQueue) Queue(begin, limit int, orderAsc ...bool) []float64 {
	return m.getElements(begin, limit, orderAsc, func(idx int) uint32 {
		return (m.head + uint32(idx)) % m.cap
	})
}

// 按栈顺序获取元素（后进先出）
func (m *NumQueue) Stack(begin, limit int, orderAsc ...bool) []float64 {
	asc := true
	if len(orderAsc) > 0 {
		asc = orderAsc[0]
	}
	//asc = !asc //stack 倒序需要取反
	return m.getElements(begin, limit, []bool{asc}, func(idx int) uint32 {
		return (m.tail - uint32(idx) - 1 + m.cap) % m.cap
	})
}

// 公共实现函数
func (m *NumQueue) getElements(begin, limit int, orderAsc []bool, posFunc func(int) uint32) []float64 {
	count := m.Len()
	if count == 0 {
		return nil
	}
	if limit == -1 {
		limit = count
	}
	if limit > count {
		limit = count
	}
	end := min(begin+limit, count)
	if end <= begin {
		return nil
	}

	asc := true
	if len(orderAsc) > 0 {
		asc = orderAsc[0]
	}

	indices := generateIndices(begin, end, asc)
	rows := make([]float64, len(indices), cap(indices)+m.reserve)

	for i, idx := range indices {
		pos := posFunc(idx)
		rows[i] = m.array[pos]
	}

	return rows
}

// // Write .
// func (m *NumQueue) Write(b []byte) (n int, err error) {
// 	e := new(G)
// 	err = json.Unmarshal(b, e)
// 	if err == nil {
// 		m.Push(e)
// 	}
// 	n = len(b)
// 	return
// }

// 求和
func (m *NumQueue) Sum() float64 {
	var sum float64
	var i uint32
	index := m.head
	for ; i < m.size; i++ {
		sum += m.array[index]
		index = (index + 1) % m.cap
	}
	return sum
}

// 计算方差
func (m *NumQueue) Variance() float64 {
	if m.size == 0 {
		return 0
	}
	avg := m.Avg()
	var sum float64
	var i uint32
	index := m.head
	for ; i < m.size; i++ {
		sum += math.Pow(m.array[index]-avg, 2)
		index = (index + 1) % m.cap
	}
	return sum / float64(m.size)
}

// 求平均值
func (m *NumQueue) Avg() float64 {
	if m.size == 0 {
		return 0
	}
	return m.Sum() / float64(m.size)
}

// 求最小值
func (m *NumQueue) Min() float64 {
	if m.size == 0 {
		return 0
	}
	min := math.MaxFloat64
	var i uint32
	index := m.head
	for ; i < m.size; i++ {
		if m.array[index] < min {
			min = m.array[index]
		}
		index = (index + 1) % m.cap
	}
	return min
}

// 求最大值
func (m *NumQueue) Max() float64 {
	if m.size == 0 {
		return 0
	}
	max := -math.MaxFloat64
	var i uint32
	index := m.head
	for ; i < m.size; i++ {
		if m.array[index] > max {
			max = m.array[index]
		}
		index = (index + 1) % m.cap
	}
	return max
}

// 求数据出现的次数
func (m *NumQueue) Count(v float64) int {
	count := 0
	var i uint32
	index := m.head
	for ; i < m.size; i++ {
		if m.array[index] == v {
			count++
		}
		index = (index + 1) % m.cap
	}
	return count
}

// 求连续出现相同数据的次数
func (m *NumQueue) CountContinuity(v float64, count int) int {
	cnt := count //局部计数器
	res := 0
	index := (m.tail - 1 + m.cap) % m.cap
	for i := 0; i < int(m.size); i++ {
		if m.array[index] == v {
			cnt--
		} else {
			if cnt <= 0 {
				res++
			}
			cnt = count
		}
		index = (index - 1 + m.cap) % m.cap
	}
	if cnt <= 0 {
		res++
	}
	return res
}
